// Angle.h
 
// Triedy, funkcie, operatory a vsetko, co suvisi s vypoctom uhlov
#ifndef ANGLE_H
#define ANGLE_H

#include <math.h>

// Microsoft math.h does not define M_PI
#ifndef M_PI
#define M_PI		3.14159265358979323846f
#endif

// Zapuzdruje zakladnu triedu pre vypocet uhlov, ci uz v radianoch alebo stupnoch
class Angle
{
	// Tu sa uklada hodnota uhlu (default su stupne)
	float deg;

protected:
	Angle(float d) : deg(d)
	{
		Normalize();
	}

	// Nastavenie uhla v radianoch
	void SetRad(float r)
	{ 
		deg = r * 180.f / M_PI; Normalize();
	}
	// Nastavenie uhla v stupnoch
	void SetDeg(float d)
	{ 
		deg = d; Normalize();
	}
	
	// Normalizuje uhol
	inline float Normalize();

public:
	// Konstruktor
	Angle() : deg(0)
	{
	
	}
	// Kopirovaci konstruktor
	Angle(const Angle& a) : deg(a.deg)
	{
	
	}

	Angle Abs() const
	{
		return Angle(fabsf(deg));
	}

	// Metody pre pristup k hodnote uhlu
	// Vrati uhol v radianoch
	float GetRad() const
	{ 
		return deg * M_PI / 180.f;
	}
	// Vrati uhol v stupnoch
	float GetDeg() const
	{
		return deg;
	}
	// Vrati absolutnu hodnotu uhlu v stupnoch
	float GetAbsDeg() const
	{ 
		return fabsf(GetDeg());
	}
	// Vrati absolutnu hodnotu uhlu v radianoch
	float GetAbsRad() const
	{
		return fabsf(GetRad()); 
	}

	// Operatory
	inline Angle operator +(const Angle& angle) const;
	inline Angle operator -(const Angle& angle) const;
	inline Angle operator *(float f) const;
	inline Angle operator /(float f) const;

	Angle operator -() const
	{ 
		return Angle(-deg);
	}

	inline const Angle& operator =(const Angle& angle);
	inline const Angle& operator +=(const Angle& angle);
	inline const Angle& operator -=(const Angle& angle);
	inline const Angle& operator *=(float f);
	inline const Angle& operator /=(float f);
	
	bool operator <(const Angle& angle) const
	{ 
		return deg < angle.deg;
	}
	bool operator >(const Angle& angle) const
	{
		return deg > angle.deg;
	}
	bool operator <=(const Angle& angle) const
	{ 
		return deg <= angle.deg; 
	}
	bool operator >=(const Angle& angle) const
	{ 
		return deg >= angle.deg; 
	}

	// Goniometricke funkcie
	float Sin() const
	{
		return sinf(GetRad());
	}
	float Cos() const
	{ 
		return cosf(GetRad());
	}
	float Tan() const
	{
		return tanf(GetRad()); 
	}
	float Cotg() const
	{ 
		return 1.f / tanf(GetRad()); 
	}
};

// Trieda pre uhly v stupnoch
class DegAngle : public Angle
{
public:
	// Konstruktor
	DegAngle(float d) : Angle()
	{
		SetDeg(d);
	}
};

// Trieda pre uhly v radianoch
class RadAngle : public Angle
{
public:
	// Konstruktor	
	RadAngle(float r) : Angle() {
		SetRad(r);
	}
};


Angle Angle::operator +(const Angle& angle) const
{
	return Angle(deg + angle.deg);
}

Angle Angle::operator -(const Angle& angle) const
{
	return Angle(deg - angle.deg);
}

Angle Angle::operator *(float f) const
{
	return Angle(deg * f);
}

Angle Angle::operator /(float f) const
{
	return Angle(deg / f);
}


const Angle& Angle::operator =(const Angle& angle)
{
	deg = angle.deg;
	return *this;
}

const Angle& Angle::operator +=(const Angle& angle)
{
	deg += angle.deg;
	Normalize();
	
	return *this;
}

const Angle& Angle::operator -=(const Angle& angle)
{
	deg -= angle.deg;
	Normalize();
	
	return *this;
}

const Angle& Angle::operator *=(float f)
{
	deg *= f;
	Normalize();
	
	return *this;
}

const Angle& Angle::operator /=(float f)
{
	deg /= f;
	Normalize();
	
	return *this;
}

float Angle::Normalize()
{
	while(deg < 180.f) 
		deg += 360.f;
	while(deg > 180.f) 
		deg -= 360.f;
	
	return deg;
}

#endif // ANGLE_H
